'use strict';

function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
import { runOnUIImmediately } from '../../threads';
import { registerEventHandler, unregisterEventHandler } from '../../core';
import { Platform } from 'react-native';
import { isJest, shouldBeUseWeb } from '../../PlatformChecker';
const IS_ANDROID = Platform.OS === 'android';
export class ProgressTransitionManager {
  constructor() {
    _defineProperty(this, "_sharedElementCount", 0);
    _defineProperty(this, "_eventHandler", {
      isRegistered: false,
      onTransitionProgress: -1,
      onAppear: -1,
      onDisappear: -1,
      onSwipeDismiss: -1
    });
  }
  addProgressAnimation(viewTag, progressAnimation) {
    runOnUIImmediately(() => {
      'worklet';

      global.ProgressTransitionRegister.addProgressAnimation(viewTag, progressAnimation);
    })();
    this.registerEventHandlers();
  }
  removeProgressAnimation(viewTag) {
    this.unregisterEventHandlers();
    runOnUIImmediately(() => {
      'worklet';

      global.ProgressTransitionRegister.removeProgressAnimation(viewTag);
    })();
  }
  registerEventHandlers() {
    this._sharedElementCount++;
    const eventHandler = this._eventHandler;
    if (!eventHandler.isRegistered) {
      eventHandler.isRegistered = true;
      const eventPrefix = IS_ANDROID ? 'on' : 'top';
      let lastProgressValue = -1;
      eventHandler.onTransitionProgress = registerEventHandler(event => {
        'worklet';

        const progress = event.progress;
        if (progress === lastProgressValue) {
          // During screen transition, handler receives two events with the same progress
          // value for both screens, but for modals, there is only one event. To optimize
          // performance and avoid unnecessary worklet calls, let's skip the second event.
          return;
        }
        lastProgressValue = progress;
        global.ProgressTransitionRegister.frame(progress);
      }, eventPrefix + 'TransitionProgress');
      eventHandler.onAppear = registerEventHandler(() => {
        'worklet';

        global.ProgressTransitionRegister.onTransitionEnd();
      }, eventPrefix + 'Appear');
      if (IS_ANDROID) {
        // onFinishTransitioning event is available only on Android and
        // is used to handle closing modals
        eventHandler.onDisappear = registerEventHandler(() => {
          'worklet';

          global.ProgressTransitionRegister.onAndroidFinishTransitioning();
        }, 'onFinishTransitioning');
      } else if (Platform.OS === 'ios') {
        // topDisappear event is required to handle closing modals on iOS
        eventHandler.onDisappear = registerEventHandler(() => {
          'worklet';

          global.ProgressTransitionRegister.onTransitionEnd(true);
        }, 'topDisappear');
        eventHandler.onSwipeDismiss = registerEventHandler(() => {
          'worklet';

          global.ProgressTransitionRegister.onTransitionEnd();
        }, 'topGestureCancel');
      }
    }
  }
  unregisterEventHandlers() {
    this._sharedElementCount--;
    if (this._sharedElementCount === 0) {
      const eventHandler = this._eventHandler;
      eventHandler.isRegistered = false;
      if (eventHandler.onTransitionProgress !== -1) {
        unregisterEventHandler(eventHandler.onTransitionProgress);
        eventHandler.onTransitionProgress = -1;
      }
      if (eventHandler.onAppear !== -1) {
        unregisterEventHandler(eventHandler.onAppear);
        eventHandler.onAppear = -1;
      }
      if (eventHandler.onDisappear !== -1) {
        unregisterEventHandler(eventHandler.onDisappear);
        eventHandler.onDisappear = -1;
      }
      if (eventHandler.onSwipeDismiss !== -1) {
        unregisterEventHandler(eventHandler.onSwipeDismiss);
        eventHandler.onSwipeDismiss = -1;
      }
    }
  }
}
function createProgressTransitionRegister() {
  'worklet';

  const progressAnimations = new Map();
  const snapshots = new Map();
  const currentTransitions = new Set();
  const toRemove = new Set();
  let skipCleaning = false;
  let isTransitionRestart = false;
  const progressTransitionManager = {
    addProgressAnimation: (viewTag, progressAnimation) => {
      if (currentTransitions.size > 0) {
        // there is no need to prevent cleaning on android
        isTransitionRestart = !IS_ANDROID;
      }
      progressAnimations.set(viewTag, progressAnimation);
    },
    removeProgressAnimation: viewTag => {
      if (currentTransitions.size > 0) {
        // there is no need to prevent cleaning on android
        isTransitionRestart = !IS_ANDROID;
      }
      // Remove the animation config after the transition is finished
      toRemove.add(viewTag);
    },
    onTransitionStart: (viewTag, snapshot) => {
      skipCleaning = isTransitionRestart;
      snapshots.set(viewTag, snapshot);
      currentTransitions.add(viewTag);
      // set initial style for re-parented components
      progressTransitionManager.frame(0);
    },
    frame: progress => {
      for (const viewTag of currentTransitions) {
        const progressAnimation = progressAnimations.get(viewTag);
        if (!progressAnimation) {
          continue;
        }
        const snapshot = snapshots.get(viewTag);
        progressAnimation(viewTag, snapshot, progress);
      }
    },
    onAndroidFinishTransitioning: () => {
      if (toRemove.size > 0) {
        // it should be ran only on modal closing
        progressTransitionManager.onTransitionEnd();
      }
    },
    onTransitionEnd: function () {
      let removeViews = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
      if (currentTransitions.size === 0) {
        toRemove.clear();
        return;
      }
      if (skipCleaning) {
        skipCleaning = false;
        isTransitionRestart = false;
        return;
      }
      for (const viewTag of currentTransitions) {
        _notifyAboutEnd(viewTag, removeViews);
      }
      currentTransitions.clear();
      if (isTransitionRestart) {
        // on transition restart, progressAnimations should be saved
        // because they potentially can be used in the next transition
        return;
      }
      snapshots.clear();
      if (toRemove.size > 0) {
        for (const viewTag of toRemove) {
          progressAnimations.delete(viewTag);
          _notifyAboutEnd(viewTag, removeViews);
        }
        toRemove.clear();
      }
    }
  };
  return progressTransitionManager;
}
if (shouldBeUseWeb()) {
  const maybeThrowError = () => {
    // Jest attempts to access a property of this object to check if it is a Jest mock
    // so we can't throw an error in the getter.
    if (!isJest()) {
      throw new Error('[Reanimated] `ProgressTransitionRegister` is not available on non-native platform.');
    }
  };
  global.ProgressTransitionRegister = new Proxy({}, {
    get: maybeThrowError,
    set: () => {
      maybeThrowError();
      return false;
    }
  });
} else {
  runOnUIImmediately(() => {
    'worklet';

    global.ProgressTransitionRegister = createProgressTransitionRegister();
  })();
}
//# sourceMappingURL=ProgressTransitionManager.js.map